/*-------------------------------------------------------------------------
 *
 * smgr.h
 *	  存储管理器开关公共接口声明。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/smgr.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef SMGR_H
#define SMGR_H

#include "lib/ilist.h"
#include "storage/block.h"
#include "storage/relfilenode.h"

/*
 * smgr.c 维护一个 SMgrRelation 对象的表，这些对象本质上是
 * 缓存的文件句柄。SMgrRelation 由 smgropen() 创建（如果尚不存在），
 * 并由 smgrclose() 销毁。请注意，这两个操作都不涉及 I/O，
 * 它们只是在创建或销毁哈希表条目。
 * （但是 smgrclose() 可能会释放相关资源，例如操作系统级文件
 * 描述符。）
 *
 * 一个 SMgrRelation 可能有一个“所有者”，这只是一个来自
 * 其他位置的指向它的指针；如果 SMgrRelation 被关闭，
 * smgr.c 将清除此指针。我们这样做是为了避免 relcache 到 smgr
 * 的悬挂指针，而不需要让 smgr 显式意识到 relcache。
 * 每个 SMgrRelation 不能有超过一个的“所有者”指针，但这正是
 * 我们所需要的。
 *
 * 没有“所有者”的 SMgrRelations 被视为临时的，
 * 并在事务结束时被删除。
 */
typedef struct SMgrRelationData
{
	/* rnode 是哈希表查找键，因此它必须是第一个! */
	RelFileNodeBackend smgr_rnode;	/* 关系物理标识符 */

	/* 指向所有者指针的指针，如果没有则为 NULL */
	struct SMgrRelationData **smgr_owner;

	/*
	 * 以下字段在缓存刷新事件时重置为 InvalidBlockNumber，
	 * 并保存每个分叉的最后已知大小。此信息当前
	 * 仅在恢复期间可靠，因为没有针对分叉扩展的缓存失效。
	 */
	BlockNumber smgr_targblock; /* 当前插入目标块 */
	BlockNumber smgr_cached_nblocks[MAX_FORKNUM + 1];	/* 最后已知大小 */

	/* 可能将来会在这里存在的其他公共字段 */

	/*
	 * 以下字段旨在对 smgr.c 及其
	 * 子模块私有。从其他地方不要触碰它们。
	 */
	int			smgr_which;		/* 存储管理器选择器 */

	/*
	 * 对于 md.c；每个分叉的开放段数的数组
	 * （md_num_open_segs）和段本身（md_seg_fds）。
	 */
	int			md_num_open_segs[MAX_FORKNUM + 1];
	struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1];

	/* 如果没有所有者，则在所有未拥有的 SMgrRelations 列表中列出链接 */
	dlist_node	node;
} SMgrRelationData;

typedef SMgrRelationData *SMgrRelation;

#define SmgrIsTemp(smgr) \
	RelFileNodeBackendIsTemp((smgr)->smgr_rnode)

extern void smgrinit(void);
extern SMgrRelation smgropen(RelFileNode rnode, BackendId backend);
extern bool smgrexists(SMgrRelation reln, ForkNumber forknum);
extern void smgrsetowner(SMgrRelation *owner, SMgrRelation reln);
extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
extern void smgrclose(SMgrRelation reln);
extern void smgrcloseall(void);
extern void smgrclosenode(RelFileNodeBackend rnode);
extern void smgrrelease(SMgrRelation reln);
extern void smgrreleaseall(void);
extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
extern void smgrdosyncall(SMgrRelation *rels, int nrels);
extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
					   BlockNumber blocknum, char *buffer, bool skipFsync);
extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum,
						 BlockNumber blocknum);
extern void smgrread(SMgrRelation reln, ForkNumber forknum,
					 BlockNumber blocknum, char *buffer);
extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,
					  BlockNumber blocknum, char *buffer, bool skipFsync);
extern void smgrwriteback(SMgrRelation reln, ForkNumber forknum,
						  BlockNumber blocknum, BlockNumber nblocks);
extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum);
extern BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum);
extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks,
						 BlockNumber *nblocks);
extern void smgrtruncate2(SMgrRelation reln, ForkNumber *forknum, int nforks,
						  BlockNumber *old_nblocks,
						  BlockNumber *nblocks);
extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum);
extern void AtEOXact_SMgr(void);
extern bool ProcessBarrierSmgrRelease(void);

#endif							/* SMGR_H */
